/**
 * Copyright (c) Tiny Technologies, Inc. All rights reserved.
 * Licensed under the LGPL or a commercial license.
 * For LGPL see License.txt in the project root for license information.
 * For commercial licenses see https://www.tiny.cloud/
 *
 * Version: 5.1.0 (2019-10-17)
 */
(function() {
	'use strict';

	var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

	var __assign = function() {
		__assign = Object.assign || function __assign(t) {
			for (var s, i = 1, n = arguments.length; i < n; i++) {
				s = arguments[i];
				for (var p in s)
					if (Object.prototype.hasOwnProperty.call(s, p))
						t[p] = s[p];
			}
			return t;
		};
		return __assign.apply(this, arguments);
	};

	var noop = function() {};
	var constant = function(value) {
		return function() {
			return value;
		};
	};
	var never = constant(false);
	var always = constant(true);

	var none = function() {
		return NONE;
	};
	var NONE = function() {
		var eq = function(o) {
			return o.isNone();
		};
		var call = function(thunk) {
			return thunk();
		};
		var id = function(n) {
			return n;
		};
		var me = {
			fold: function(n, s) {
				return n();
			},
			is: never,
			isSome: never,
			isNone: always,
			getOr: id,
			getOrThunk: call,
			getOrDie: function(msg) {
				throw new Error(msg || 'error: getOrDie called on none.');
			},
			getOrNull: constant(null),
			getOrUndefined: constant(undefined),
			or: id,
			orThunk: call,
			map: none,
			each: noop,
			bind: none,
			exists: never,
			forall: always,
			filter: none,
			equals: eq,
			equals_: eq,
			toArray: function() {
				return [];
			},
			toString: constant('none()')
		};
		if (Object.freeze) {
			Object.freeze(me);
		}
		return me;
	}();
	var some = function(a) {
		var constant_a = constant(a);
		var self = function() {
			return me;
		};
		var bind = function(f) {
			return f(a);
		};
		var me = {
			fold: function(n, s) {
				return s(a);
			},
			is: function(v) {
				return a === v;
			},
			isSome: always,
			isNone: never,
			getOr: constant_a,
			getOrThunk: constant_a,
			getOrDie: constant_a,
			getOrNull: constant_a,
			getOrUndefined: constant_a,
			or: self,
			orThunk: self,
			map: function(f) {
				return some(f(a));
			},
			each: function(f) {
				f(a);
			},
			bind: bind,
			exists: bind,
			forall: bind,
			filter: function(f) {
				return f(a) ? me : NONE;
			},
			toArray: function() {
				return [a];
			},
			toString: function() {
				return 'some(' + a + ')';
			},
			equals: function(o) {
				return o.is(a);
			},
			equals_: function(o, elementEq) {
				return o.fold(never, function(b) {
					return elementEq(a, b);
				});
			}
		};
		return me;
	};
	var from = function(value) {
		return value === null || value === undefined ? NONE : some(value);
	};
	var Option = {
		some: some,
		none: none,
		from: from
	};

	var typeOf = function(x) {
		if (x === null) {
			return 'null';
		}
		var t = typeof x;
		if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name ===
				'Array')) {
			return 'array';
		}
		if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name ===
				'String')) {
			return 'string';
		}
		return t;
	};
	var isType = function(type) {
		return function(value) {
			return typeOf(value) === type;
		};
	};
	var isString = isType('string');
	var isArray = isType('array');
	var isFunction = isType('function');

	var nativeSlice = Array.prototype.slice;
	var nativePush = Array.prototype.push;
	var each = function(xs, f) {
		for (var i = 0, len = xs.length; i < len; i++) {
			var x = xs[i];
			f(x, i);
		}
	};
	var flatten = function(xs) {
		var r = [];
		for (var i = 0, len = xs.length; i < len; ++i) {
			if (!isArray(xs[i])) {
				throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
			}
			nativePush.apply(r, xs[i]);
		}
		return r;
	};
	var from$1 = isFunction(Array.from) ? Array.from : function(x) {
		return nativeSlice.call(x);
	};

	var Cell = function(initial) {
		var value = initial;
		var get = function() {
			return value;
		};
		var set = function(v) {
			value = v;
		};
		var clone = function() {
			return Cell(get());
		};
		return {
			get: get,
			set: set,
			clone: clone
		};
	};

	var hasOwnProperty = Object.prototype.hasOwnProperty;
	var shallow = function(old, nu) {
		return nu;
	};
	var baseMerge = function(merger) {
		return function() {
			var objects = new Array(arguments.length);
			for (var i = 0; i < objects.length; i++) {
				objects[i] = arguments[i];
			}
			if (objects.length === 0) {
				throw new Error('Can\'t merge zero objects');
			}
			var ret = {};
			for (var j = 0; j < objects.length; j++) {
				var curObject = objects[j];
				for (var key in curObject) {
					if (hasOwnProperty.call(curObject, key)) {
						ret[key] = merger(ret[key], curObject[key]);
					}
				}
			}
			return ret;
		};
	};
	var merge = baseMerge(shallow);

	var hasOwnProperty$1 = Object.hasOwnProperty;
	var get = function(obj, key) {
		return has(obj, key) ? Option.from(obj[key]) : Option.none();
	};
	var has = function(obj, key) {
		return hasOwnProperty$1.call(obj, key);
	};

	var getScripts = function(editor) {
		return editor.getParam('media_scripts');
	};
	var getAudioTemplateCallback = function(editor) {
		return editor.getParam('audio_template_callback');
	};
	var getVideoTemplateCallback = function(editor) {
		return editor.getParam('video_template_callback');
	};
	var hasLiveEmbeds = function(editor) {
		return editor.getParam('media_live_embeds', true);
	};
	var shouldFilterHtml = function(editor) {
		return editor.getParam('media_filter_html', true);
	};
	var getUrlResolver = function(editor) {
		return editor.getParam('media_url_resolver');
	};
	var hasAltSource = function(editor) {
		return editor.getParam('media_alt_source', true);
	};
	var hasPoster = function(editor) {
		return editor.getParam('media_poster', true);
	};
	var hasDimensions = function(editor) {
		return editor.getParam('media_dimensions', true);
	};
	var Settings = {
		getScripts: getScripts,
		getAudioTemplateCallback: getAudioTemplateCallback,
		getVideoTemplateCallback: getVideoTemplateCallback,
		hasLiveEmbeds: hasLiveEmbeds,
		shouldFilterHtml: shouldFilterHtml,
		getUrlResolver: getUrlResolver,
		hasAltSource: hasAltSource,
		hasPoster: hasPoster,
		hasDimensions: hasDimensions
	};

	var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');

	var global$2 = tinymce.util.Tools.resolve('tinymce.html.SaxParser');

	var global$3 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');

	var trimPx = function(value) {
		return value.replace(/px$/, '');
	};
	var addPx = function(value) {
		return /^[0-9.]+$/.test(value) ? value + 'px' : value;
	};
	var getSize = function(name) {
		return function(elm) {
			return elm ? trimPx(elm.style[name]) : '';
		};
	};
	var setSize = function(name) {
		return function(elm, value) {
			if (elm) {
				elm.style[name] = addPx(value);
			}
		};
	};
	var Size = {
		getMaxWidth: getSize('maxWidth'),
		getMaxHeight: getSize('maxHeight'),
		setMaxWidth: setSize('maxWidth'),
		setMaxHeight: setSize('maxHeight')
	};

	var getVideoScriptMatch = function(prefixes, src) {
		if (prefixes) {
			for (var i = 0; i < prefixes.length; i++) {
				if (src.indexOf(prefixes[i].filter) !== -1) {
					return prefixes[i];
				}
			}
		}
	};

	var DOM = global$3.DOM;
	var getEphoxEmbedIri = function(elm) {
		return DOM.getAttrib(elm, 'data-ephox-embed-iri');
	};
	var isEphoxEmbed = function(html) {
		var fragment = DOM.createFragment(html);
		return getEphoxEmbedIri(fragment.firstChild) !== '';
	};
	var htmlToDataSax = function(prefixes, html) {
		var data = {};
		global$2({
			validate: false,
			allow_conditional_comments: true,
			start: function(name, attrs) {
				if (!data.source1 && name === 'param') {
					data.source1 = attrs.map.movie;
				}
				if (name === 'iframe' || name === 'object' || name === 'embed' || name ===
					'video' || name === 'audio') {
					if (!data.type) {
						data.type = name;
					}
					data = global$1.extend(attrs.map, data);
				}
				if (name === 'script') {
					var videoScript = getVideoScriptMatch(prefixes, attrs.map.src);
					if (!videoScript) {
						return;
					}
					data = {
						type: 'script',
						source1: attrs.map.src,
						width: String(videoScript.width),
						height: String(videoScript.height)
					};
				}
				if (name === 'source') {
					if (!data.source1) {
						data.source1 = attrs.map.src;
					} else if (!data.source2) {
						data.source2 = attrs.map.src;
					}
				}
				if (name === 'img' && !data.poster) {
					data.poster = attrs.map.src;
				}
			}
		}).parse(html);
		data.source1 = data.source1 || data.src || data.data;
		data.source2 = data.source2 || '';
		data.poster = data.poster || '';
		return data;
	};
	var ephoxEmbedHtmlToData = function(html) {
		var fragment = DOM.createFragment(html);
		var div = fragment.firstChild;
		return {
			type: 'ephox-embed-iri',
			source1: getEphoxEmbedIri(div),
			source2: '',
			poster: '',
			width: Size.getMaxWidth(div),
			height: Size.getMaxHeight(div)
		};
	};
	var htmlToData = function(prefixes, html) {
		return isEphoxEmbed(html) ? ephoxEmbedHtmlToData(html) : htmlToDataSax(prefixes, html);
	};

	var global$4 = tinymce.util.Tools.resolve('tinymce.util.Promise');

	var guess = function(url) {
		var mimes = {
			mp3: 'audio/mpeg',
			m4a: 'audio/x-m4a',
			wav: 'audio/wav',
			mp4: 'video/mp4',
			webm: 'video/webm',
			ogg: 'video/ogg',
			swf: 'application/x-shockwave-flash'
		};
		var fileEnd = url.toLowerCase().split('.').pop();
		var mime = mimes[fileEnd];
		return mime ? mime : '';
	};
	var Mime = {
		guess: guess
	};

	var global$5 = tinymce.util.Tools.resolve('tinymce.html.Writer');

	var global$6 = tinymce.util.Tools.resolve('tinymce.html.Schema');

	var DOM$1 = global$3.DOM;
	var setAttributes = function(attrs, updatedAttrs) {
		var name;
		var i;
		var value;
		var attr;
		for (name in updatedAttrs) {
			value = '' + updatedAttrs[name];
			if (attrs.map[name]) {
				i = attrs.length;
				while (i--) {
					attr = attrs[i];
					if (attr.name === name) {
						if (value) {
							attrs.map[name] = value;
							attr.value = value;
						} else {
							delete attrs.map[name];
							attrs.splice(i, 1);
						}
					}
				}
			} else if (value) {
				attrs.push({
					name: name,
					value: value
				});
				attrs.map[name] = value;
			}
		}
	};
	var normalizeHtml = function(html) {
		var writer = global$5();
		var parser = global$2(writer);
		parser.parse(html);
		return writer.getContent();
	};
	var updateHtmlSax = function(html, data, updateAll) {
		var writer = global$5();
		var sourceCount = 0;
		var hasImage;
		global$2({
			validate: false,
			allow_conditional_comments: true,
			comment: function(text) {
				writer.comment(text);
			},
			cdata: function(text) {
				writer.cdata(text);
			},
			text: function(text, raw) {
				writer.text(text, raw);
			},
			start: function(name, attrs, empty) {
				switch (name) {
					case 'video':
					case 'object':
					case 'embed':
					case 'img':
					case 'iframe':
						if (data.height !== undefined && data.width !== undefined) {
							setAttributes(attrs, {
								width: data.width,
								height: data.height
							});
						}
						break;
				}
				if (updateAll) {
					switch (name) {
						case 'video':
							setAttributes(attrs, {
								poster: data.poster,
								src: ''
							});
							if (data.source2) {
								setAttributes(attrs, {
									src: ''
								});
							}
							break;
						case 'iframe':
							setAttributes(attrs, {
								src: data.source1
							});
							break;
						case 'source':
							sourceCount++;
							if (sourceCount <= 2) {
								setAttributes(attrs, {
									src: data['source' + sourceCount],
									type: data['source' + sourceCount + 'mime']
								});
								if (!data['source' + sourceCount]) {
									return;
								}
							}
							break;
						case 'img':
							if (!data.poster) {
								return;
							}
							hasImage = true;
							break;
					}
				}
				writer.start(name, attrs, empty);
			},
			end: function(name) {
				if (name === 'video' && updateAll) {
					for (var index = 1; index <= 2; index++) {
						if (data['source' + index]) {
							var attrs = [];
							attrs.map = {};
							if (sourceCount < index) {
								setAttributes(attrs, {
									src: data['source' + index],
									type: data['source' + index + 'mime']
								});
								writer.start('source', attrs, true);
							}
						}
					}
				}
				if (data.poster && name === 'object' && updateAll && !hasImage) {
					var imgAttrs = [];
					imgAttrs.map = {};
					setAttributes(imgAttrs, {
						src: data.poster,
						width: data.width,
						height: data.height
					});
					writer.start('img', imgAttrs, true);
				}
				writer.end(name);
			}
		}, global$6({})).parse(html);
		return writer.getContent();
	};
	var isEphoxEmbed$1 = function(html) {
		var fragment = DOM$1.createFragment(html);
		return DOM$1.getAttrib(fragment.firstChild, 'data-ephox-embed-iri') !== '';
	};
	var updateEphoxEmbed = function(html, data) {
		var fragment = DOM$1.createFragment(html);
		var div = fragment.firstChild;
		Size.setMaxWidth(div, data.width);
		Size.setMaxHeight(div, data.height);
		return normalizeHtml(div.outerHTML);
	};
	var updateHtml = function(html, data, updateAll) {
		return isEphoxEmbed$1(html) ? updateEphoxEmbed(html, data) : updateHtmlSax(html, data, updateAll);
	};
	var UpdateHtml = {
		updateHtml: updateHtml
	};

	var urlPatterns = [{
			regex: /youtu\.be\/([\w\-_\?&=.]+)/i,
			type: 'iframe',
			w: 560,
			h: 314,
			url: '//www.youtube.com/embed/$1',
			allowFullscreen: true
		},
		{
			regex: /youtube\.com(.+)v=([^&]+)(&([a-z0-9&=\-_]+))?/i,
			type: 'iframe',
			w: 560,
			h: 314,
			url: '//www.youtube.com/embed/$2?$4',
			allowFullscreen: true
		},
		{
			regex: /youtube.com\/embed\/([a-z0-9\?&=\-_]+)/i,
			type: 'iframe',
			w: 560,
			h: 314,
			url: '//www.youtube.com/embed/$1',
			allowFullscreen: true
		},
		{
			regex: /vimeo\.com\/([0-9]+)/,
			type: 'iframe',
			w: 425,
			h: 350,
			url: '//player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc',
			allowFullscreen: true
		},
		{
			regex: /vimeo\.com\/(.*)\/([0-9]+)/,
			type: 'iframe',
			w: 425,
			h: 350,
			url: '//player.vimeo.com/video/$2?title=0&amp;byline=0',
			allowFullscreen: true
		},
		{
			regex: /maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,
			type: 'iframe',
			w: 425,
			h: 350,
			url: '//maps.google.com/maps/ms?msid=$2&output=embed"',
			allowFullscreen: false
		},
		{
			regex: /dailymotion\.com\/video\/([^_]+)/,
			type: 'iframe',
			w: 480,
			h: 270,
			url: '//www.dailymotion.com/embed/video/$1',
			allowFullscreen: true
		},
		{
			regex: /dai\.ly\/([^_]+)/,
			type: 'iframe',
			w: 480,
			h: 270,
			url: '//www.dailymotion.com/embed/video/$1',
			allowFullscreen: true
		}
	];
	var getUrl = function(pattern, url) {
		var match = pattern.regex.exec(url);
		var newUrl = pattern.url;
		var _loop_1 = function(i) {
			newUrl = newUrl.replace('$' + i, function() {
				return match[i] ? match[i] : '';
			});
		};
		for (var i = 0; i < match.length; i++) {
			_loop_1(i);
		}
		return newUrl.replace(/\?$/, '');
	};
	var matchPattern = function(url) {
		var pattern = urlPatterns.filter(function(pattern) {
			return pattern.regex.test(url);
		});
		if (pattern.length > 0) {
			return global$1.extend({}, pattern[0], {
				url: getUrl(pattern[0], url)
			});
		} else {
			return null;
		}
	};

	var getIframeHtml = function(data) {
		var allowFullscreen = data.allowFullscreen ? ' allowFullscreen="1"' : '';
		return '<iframe src="' + data.source1 + '" width="' + data.width + '" height="' + data.height +
			'"' + allowFullscreen + '></iframe>';
	};
	var getFlashHtml = function(data) {
		var html = '<object data="' + data.source1 + '" width="' + data.width + '" height="' + data.height +
			'" type="application/x-shockwave-flash">';
		if (data.poster) {
			html += '<img src="' + data.poster + '" width="' + data.width + '" height="' + data.height +
				'" />';
		}
		html += '</object>';
		return html;
	};
	var getAudioHtml = function(data, audioTemplateCallback) {
		if (audioTemplateCallback) {
			return audioTemplateCallback(data);
		} else {
			return '<audio controls="controls" src="' + data.source1 + '">' + (data.source2 ?
				'\n<source src="' + data.source2 + '"' + (data.source2mime ? ' type="' + data
					.source2mime + '"' : '') + ' />\n' : '') + '</audio>';
		}
	};
	var getVideoHtml = function(data, videoTemplateCallback) {
		if (videoTemplateCallback) {
			return videoTemplateCallback(data);
		} else {
			return '<video width="' + data.width + '" height="' + data.height + '"' + (data.poster ?
					' poster="' + data.poster + '"' : '') + ' controls="controls">\n' + '<source src="' +
				data.source1 + '"' + (data.source1mime ? ' type="' + data.source1mime + '"' : '') +
				' />\n' + (data.source2 ? '<source src="' + data.source2 + '"' + (data.source2mime ?
					' type="' + data.source2mime + '"' : '') + ' />\n' : '') + '</video>';
		}
	};
	var getScriptHtml = function(data) {
		return '<script src="' + data.source1 + '"></script>';
	};
	var dataToHtml = function(editor, dataIn) {
		var data = global$1.extend({}, dataIn);
		if (!data.source1) {
			global$1.extend(data, htmlToData(Settings.getScripts(editor), data.embed));
			if (!data.source1) {
				return '';
			}
		}
		if (!data.source2) {
			data.source2 = '';
		}
		if (!data.poster) {
			data.poster = '';
		}
		data.source1 = editor.convertURL(data.source1, 'source');
		data.source2 = editor.convertURL(data.source2, 'source');
		data.source1mime = Mime.guess(data.source1);
		data.source2mime = Mime.guess(data.source2);
		data.poster = editor.convertURL(data.poster, 'poster');
		var pattern = matchPattern(data.source1);
		if (pattern) {
			data.source1 = pattern.url;
			data.type = pattern.type;
			data.allowFullscreen = pattern.allowFullscreen;
			data.width = data.width || String(pattern.w);
			data.height = data.height || String(pattern.h);
		}
		if (data.embed) {
			return UpdateHtml.updateHtml(data.embed, data, true);
		} else {
			var videoScript = getVideoScriptMatch(Settings.getScripts(editor), data.source1);
			if (videoScript) {
				data.type = 'script';
				data.width = String(videoScript.width);
				data.height = String(videoScript.height);
			}
			var audioTemplateCallback = Settings.getAudioTemplateCallback(editor);
			var videoTemplateCallback = Settings.getVideoTemplateCallback(editor);
			data.width = data.width || '300';
			data.height = data.height || '150';
			global$1.each(data, function(value, key) {
				data[key] = editor.dom.encode('' + value);
			});
			if (data.type === 'iframe') {
				return getIframeHtml(data);
			} else if (data.source1mime === 'application/x-shockwave-flash') {
				return getFlashHtml(data);
			} else if (data.source1mime.indexOf('audio') !== -1) {
				return getAudioHtml(data, audioTemplateCallback);
			} else if (data.type === 'script') {
				return getScriptHtml(data);
			} else {
				return getVideoHtml(data, videoTemplateCallback);
			}
		}
	};

	var cache = {};
	var embedPromise = function(data, dataToHtml, handler) {
		return new global$4(function(res, rej) {
			var wrappedResolve = function(response) {
				if (response.html) {
					cache[data.source1] = response;
				}
				return res({
					url: data.source1,
					html: response.html ? response.html : dataToHtml(data)
				});
			};
			if (cache[data.source1]) {
				wrappedResolve(cache[data.source1]);
			} else {
				handler({
					url: data.source1
				}, wrappedResolve, rej);
			}
		});
	};
	var defaultPromise = function(data, dataToHtml) {
		return new global$4(function(res) {
			res({
				html: dataToHtml(data),
				url: data.source1
			});
		});
	};
	var loadedData = function(editor) {
		return function(data) {
			return dataToHtml(editor, data);
		};
	};
	var getEmbedHtml = function(editor, data) {
		var embedHandler = Settings.getUrlResolver(editor);
		return embedHandler ? embedPromise(data, loadedData(editor), embedHandler) : defaultPromise(data,
			loadedData(editor));
	};
	var isCached = function(url) {
		return cache.hasOwnProperty(url);
	};
	var Service = {
		getEmbedHtml: getEmbedHtml,
		isCached: isCached
	};

	var unwrap = function(data) {
		var unwrapped = merge(data, {
			source1: data.source1.value,
			source2: get(data, 'source2').bind(function(source2) {
				return get(source2, 'value');
			}).getOr(''),
			poster: get(data, 'poster').bind(function(poster) {
				return get(poster, 'value');
			}).getOr('')
		});
		get(data, 'dimensions').each(function(dimensions) {
			each([
				'width',
				'height'
			], function(prop) {
				get(dimensions, prop).each(function(value) {
					return unwrapped[prop] = value;
				});
			});
		});
		return unwrapped;
	};
	var wrap = function(data) {
		var wrapped = merge(data, {
			source1: {
				value: get(data, 'source1').getOr('')
			},
			source2: {
				value: get(data, 'source2').getOr('')
			},
			poster: {
				value: get(data, 'poster').getOr('')
			}
		});
		each([
			'width',
			'height'
		], function(prop) {
			get(data, prop).each(function(value) {
				var dimensions = wrapped.dimensions || {};
				dimensions[prop] = value;
				wrapped.dimensions = dimensions;
			});
		});
		return wrapped;
	};
	var handleError = function(editor) {
		return function(error) {
			var errorMessage = error && error.msg ? 'Media embed handler error: ' + error.msg :
				'Media embed handler threw unknown error.';
			editor.notificationManager.open({
				type: 'error',
				text: errorMessage
			});
		};
	};
	var snippetToData = function(editor, embedSnippet) {
		return htmlToData(Settings.getScripts(editor), embedSnippet);
	};
	var isMediaElement = function(element) {
		return element.getAttribute('data-mce-object') || element.getAttribute('data-ephox-embed-iri');
	};
	var getEditorData = function(editor) {
		var element = editor.selection.getNode();
		var snippet = isMediaElement(element) ? editor.serializer.serialize(element, {
			selection: true
		}) : '';
		return merge({
			embed: snippet
		}, htmlToData(Settings.getScripts(editor), snippet));
	};
	var addEmbedHtml = function(api, editor) {
		return function(response) {
			if (isString(response.url) && response.url.trim().length > 0) {
				var html = response.html;
				var snippetData = snippetToData(editor, html);
				var nuData = __assign(__assign({}, snippetData), {
					source1: response.url,
					embed: html
				});
				api.setData(wrap(nuData));
			}
		};
	};
	var selectPlaceholder = function(editor, beforeObjects) {
		var afterObjects = editor.dom.select('img[data-mce-object]');
		for (var i = 0; i < beforeObjects.length; i++) {
			for (var y = afterObjects.length - 1; y >= 0; y--) {
				if (beforeObjects[i] === afterObjects[y]) {
					afterObjects.splice(y, 1);
				}
			}
		}
		editor.selection.select(afterObjects[0]);
	};
	var handleInsert = function(editor, html) {
		var beforeObjects = editor.dom.select('img[data-mce-object]');
		editor.insertContent(html);
		selectPlaceholder(editor, beforeObjects);
		editor.nodeChanged();
	};
	var submitForm = function(prevData, newData, editor) {
		newData.embed = UpdateHtml.updateHtml(newData.embed, newData);
		if (newData.embed && (prevData.source1 === newData.source1 || Service.isCached(newData.source1))) {
			handleInsert(editor, newData.embed);
		} else {
			Service.getEmbedHtml(editor, newData).then(function(response) {
				handleInsert(editor, response.html);
			}).catch(handleError(editor));
		}
	};
	var showDialog = function(editor) {
		var editorData = getEditorData(editor);
		var currentData = Cell(editorData);
		var initialData = wrap(editorData);
		var getSourceData = function(api) {
			return unwrap(api.getData());
		};
		var handleSource1 = function(prevData, api) {
			var serviceData = getSourceData(api);
			if (prevData.source1 !== serviceData.source1) {
				addEmbedHtml(win, editor)({
					url: serviceData.source1,
					html: ''
				});
				Service.getEmbedHtml(editor, serviceData).then(addEmbedHtml(win, editor)).catch(
					handleError(editor));
			}
		};
		var handleEmbed = function(api) {
			var data = unwrap(api.getData());
			var dataFromEmbed = snippetToData(editor, data.embed);
			api.setData(wrap(dataFromEmbed));
		};
		var handleUpdate = function(api) {
			var data = getSourceData(api);
			var embed = dataToHtml(editor, data);
			api.setData(wrap(__assign(__assign({}, data), {
				embed: embed
			})));
		};
		var mediaInput = [{
			name: 'source1',
			type: 'urlinput',
			filetype: 'media',
			label: 'Source'
		}];
		var sizeInput = !Settings.hasDimensions(editor) ? [] : [{
			type: 'sizeinput',
			name: 'dimensions',
			label: 'Constrain proportions',
			constrain: true
		}];
		var generalTab = {
			title: 'General',
			name: 'general',
			items: flatten([
				mediaInput,
				sizeInput
			])
		};
		var embedTextarea = {
			type: 'textarea',
			name: 'embed',
			label: 'Paste your embed code below:'
		};
		var embedTab = {
			title: 'Embed',
			items: [embedTextarea]
		};
		var advancedFormItems = [];
		if (Settings.hasAltSource(editor)) {
			advancedFormItems.push({
				name: 'source2',
				type: 'urlinput',
				filetype: 'media',
				label: 'Alternative source URL'
			});
		}
		if (Settings.hasPoster(editor)) {
			advancedFormItems.push({
				name: 'poster',
				type: 'urlinput',
				filetype: 'image',
				label: 'Media poster (Image URL)'
			});
		}
		var advancedTab = {
			title: 'Advanced',
			name: 'advanced',
			items: advancedFormItems
		};
		var tabs = [
			generalTab,
			embedTab
		];
		if (advancedFormItems.length > 0) {
			tabs.push(advancedTab);
		}
		var body = {
			type: 'tabpanel',
			tabs: tabs
		};
		var win = editor.windowManager.open({
			title: 'Insert/Edit Media',
			size: 'normal',
			body: body,
			buttons: [{
					type: 'cancel',
					name: 'cancel',
					text: 'Cancel'
				},
				{
					type: 'submit',
					name: 'save',
					text: 'Save',
					primary: true
				}
			],
			onSubmit: function(api) {
				var serviceData = getSourceData(api);
				submitForm(currentData.get(), serviceData, editor);
				api.close();
			},
			onChange: function(api, detail) {
				switch (detail.name) {
					case 'source1':
						handleSource1(currentData.get(), api);
						break;
					case 'embed':
						handleEmbed(api);
						break;
					case 'dimensions':
					case 'poster':
						handleUpdate(api);
						break;
					default:
						break;
				}
				currentData.set(getSourceData(api));
			},
			initialData: initialData
		});
	};
	var Dialog = {
		showDialog: showDialog
	};

	var get$1 = function(editor) {
		var showDialog = function() {
			Dialog.showDialog(editor);
		};
		return {
			showDialog: showDialog
		};
	};
	var Api = {
		get: get$1
	};

	var register = function(editor) {
		var showDialog = function() {
			Dialog.showDialog(editor);
		};
		editor.addCommand('mceMedia', showDialog);
	};
	var Commands = {
		register: register
	};

	var global$7 = tinymce.util.Tools.resolve('tinymce.html.Node');

	var global$8 = tinymce.util.Tools.resolve('tinymce.Env');

	var sanitize = function(editor, html) {
		if (Settings.shouldFilterHtml(editor) === false) {
			return html;
		}
		var writer = global$5();
		var blocked;
		global$2({
			validate: false,
			allow_conditional_comments: false,
			comment: function(text) {
				writer.comment(text);
			},
			cdata: function(text) {
				writer.cdata(text);
			},
			text: function(text, raw) {
				writer.text(text, raw);
			},
			start: function(name, attrs, empty) {
				blocked = true;
				if (name === 'script' || name === 'noscript') {
					return;
				}
				for (var i = 0; i < attrs.length; i++) {
					if (attrs[i].name.indexOf('on') === 0) {
						return;
					}
					if (attrs[i].name === 'style') {
						attrs[i].value = editor.dom.serializeStyle(editor.dom.parseStyle(attrs[
							i].value), name);
					}
				}
				writer.start(name, attrs, empty);
				blocked = false;
			},
			end: function(name) {
				if (blocked) {
					return;
				}
				writer.end(name);
			}
		}, global$6({})).parse(html);
		return writer.getContent();
	};
	var Sanitize = {
		sanitize: sanitize
	};

	var createPlaceholderNode = function(editor, node) {
		var placeHolder;
		var name = node.name;
		placeHolder = new global$7('img', 1);
		placeHolder.shortEnded = true;
		retainAttributesAndInnerHtml(editor, node, placeHolder);
		placeHolder.attr({
			'width': node.attr('width') || '300',
			'height': node.attr('height') || (name === 'audio' ? '30' : '150'),
			'style': node.attr('style'),
			'src': global$8.transparentSrc,
			'data-mce-object': name,
			'class': 'mce-object mce-object-' + name
		});
		return placeHolder;
	};
	var createPreviewIframeNode = function(editor, node) {
		var previewWrapper;
		var previewNode;
		var shimNode;
		var name = node.name;
		previewWrapper = new global$7('span', 1);
		previewWrapper.attr({
			'contentEditable': 'false',
			'style': node.attr('style'),
			'data-mce-object': name,
			'class': 'mce-preview-object mce-object-' + name
		});
		retainAttributesAndInnerHtml(editor, node, previewWrapper);
		previewNode = new global$7(name, 1);
		//Lc魔改开始部分
		if (name == 'video') {
			var vd = node.attributes.map;
			var b = /<source([\s]+|[\s]+[^<>]+[\s]+)src=(\"([^<>"\']*)\"|\'([^<>"\']*)\')[^<>]*>/gi;
			// var s=vd.toLowerCase().match(b);
			var src = RegExp.$3;
			previewNode.attr({
				src: vd.src,
				controls: vd.controls, //显示播放工具就取消这行的注释
				allowfullscreen: node.attr('allowfullscreen'),
				style: node.attr('style'),
				class: node.attr('class'),
				width: vd.width,
				height: vd.height,
				frameborder: '0'
			});
		} else {
			previewNode.attr({
				src: vd.src,
				controls: vd.controls, //显示播放工具就取消这行的注释
				allowfullscreen: node.attr('allowfullscreen'),
				style: node.attr('style'),
				class: node.attr('class'),
				width: vd.width,
				height: vd.height,
				frameborder: '0'
			});
		}
		//Lc魔改结束部分

		shimNode = new global$7('span', 1);
		shimNode.attr('class', 'mce-shim');
		previewWrapper.append(previewNode);
		previewWrapper.append(shimNode);
		return previewWrapper;
	};
	var retainAttributesAndInnerHtml = function(editor, sourceNode, targetNode) {
		var attrName;
		var attrValue;
		var attribs;
		var ai;
		var innerHtml;
		attribs = sourceNode.attributes;
		ai = attribs.length;
		while (ai--) {
			attrName = attribs[ai].name;
			attrValue = attribs[ai].value;
			if (attrName !== 'width' && attrName !== 'height' && attrName !== 'style') {
				if (attrName === 'data' || attrName === 'src') {
					attrValue = editor.convertURL(attrValue, attrName);
				}
				targetNode.attr('data-mce-p-' + attrName, attrValue);
			}
		}
		innerHtml = sourceNode.firstChild && sourceNode.firstChild.value;
		if (innerHtml) {
			targetNode.attr('data-mce-html', escape(Sanitize.sanitize(editor, innerHtml)));
			targetNode.firstChild = null;
		}
	};
	var isPageEmbedWrapper = function(node) {
		var nodeClass = node.attr('class');
		return nodeClass && /\btiny-pageembed\b/.test(nodeClass);
	};
	var isWithinEmbedWrapper = function(node) {
		while (node = node.parent) {
			if (node.attr('data-ephox-embed-iri') || isPageEmbedWrapper(node)) {
				return true;
			}
		}
		return false;
	};
	var placeHolderConverter = function(editor) {
		return function(nodes) {
			var i = nodes.length;
			var node;
			var videoScript;
			while (i--) {
				node = nodes[i];
				if (!node.parent) {
					continue;
				}
				if (node.parent.attr('data-mce-object')) {
					continue;
				}
				if (node.name === 'script') {
					videoScript = getVideoScriptMatch(Settings.getScripts(editor), node.attr('src'));
					if (!videoScript) {
						continue;
					}
				}
				if (videoScript) {
					if (videoScript.width) {
						node.attr('width', videoScript.width.toString());
					}
					if (videoScript.height) {
						node.attr('height', videoScript.height.toString());
					}
				}
				//if (node.name === 'iframe' && Settings.hasLiveEmbeds(editor) && global$8.ceFalse) {
				if (Settings.hasLiveEmbeds(editor) && global$8.ceFalse) {
					if (!isWithinEmbedWrapper(node)) {
						node.replace(createPreviewIframeNode(editor, node));
					}
				} else {
					if (!isWithinEmbedWrapper(node)) {
						node.replace(createPlaceholderNode(editor, node));
					}
				}
			}
		};
	};
	var Nodes = {
		createPreviewIframeNode: createPreviewIframeNode,
		createPlaceholderNode: createPlaceholderNode,
		placeHolderConverter: placeHolderConverter
	};

	var setup = function(editor) {
		editor.on('preInit', function() {
			var specialElements = editor.schema.getSpecialElements();
			global$1.each('video audio iframe object'.split(' '), function(name) {
				specialElements[name] = new RegExp('</' + name + '[^>]*>', 'gi');
			});
			var boolAttrs = editor.schema.getBoolAttrs();
			global$1.each('webkitallowfullscreen mozallowfullscreen allowfullscreen'.split(' '),
				function(name) {
					boolAttrs[name] = {};
				});
			editor.parser.addNodeFilter('iframe,video,audio,object,embed,script', Nodes
				.placeHolderConverter(editor));
			editor.serializer.addAttributeFilter('data-mce-object', function(nodes, name) {
				var i = nodes.length;
				var node;
				var realElm;
				var ai;
				var attribs;
				var innerHtml;
				var innerNode;
				var realElmName;
				var className;
				while (i--) {
					node = nodes[i];
					if (!node.parent) {
						continue;
					}
					realElmName = node.attr(name);
					realElm = new global$7(realElmName, 1);
					if (realElmName !== 'audio' && realElmName !== 'script') {
						className = node.attr('class');
						if (className && className.indexOf('mce-preview-object') !== -1) {
							realElm.attr({
								width: node.firstChild.attr('width'),
								height: node.firstChild.attr('height')
							});
						} else {
							realElm.attr({
								width: node.attr('width'),
								height: node.attr('height')
							});
						}
					}
					realElm.attr({
						style: node.attr('style')
					});
					attribs = node.attributes;
					ai = attribs.length;
					while (ai--) {
						var attrName = attribs[ai].name;
						if (attrName.indexOf('data-mce-p-') === 0) {
							realElm.attr(attrName.substr(11), attribs[ai].value);
						}
					}
					if (realElmName === 'script') {
						realElm.attr('type', 'text/javascript');
					}
					innerHtml = node.attr('data-mce-html');
					if (innerHtml) {
						innerNode = new global$7('#text', 3);
						innerNode.raw = true;
						innerNode.value = Sanitize.sanitize(editor, unescape(innerHtml));
						realElm.append(innerNode);
					}
					node.replace(realElm);
				}
			});
		});
		editor.on('SetContent', function() {
			editor.$('span.mce-preview-object').each(function(index, elm) {
				var $elm = editor.$(elm);
				if ($elm.find('span.mce-shim').length === 0) {
					$elm.append('<span class="mce-shim"></span>');
				}
			});
		});
	};
	var FilterContent = {
		setup: setup
	};

	var setup$1 = function(editor) {
		editor.on('ResolveName', function(e) {
			var name;
			if (e.target.nodeType === 1 && (name = e.target.getAttribute('data-mce-object'))) {
				e.name = name;
			}
		});
	};
	var ResolveName = {
		setup: setup$1
	};

	var setup$2 = function(editor) {
		editor.on('click keyup touchend', function() {
			var selectedNode = editor.selection.getNode();
			if (selectedNode && editor.dom.hasClass(selectedNode, 'mce-preview-object')) {
				if (editor.dom.getAttrib(selectedNode, 'data-mce-selected')) {
					selectedNode.setAttribute('data-mce-selected', '2');
				}
			}
		});
		editor.on('ObjectSelected', function(e) {
			var objectType = e.target.getAttribute('data-mce-object');
			if (objectType === 'audio' || objectType === 'script') {
				e.preventDefault();
			}
		});
		editor.on('ObjectResized', function(e) {
			var target = e.target;
			var html;
			if (target.getAttribute('data-mce-object')) {
				html = target.getAttribute('data-mce-html');
				if (html) {
					html = unescape(html);
					target.setAttribute('data-mce-html', escape(UpdateHtml.updateHtml(html, {
						width: String(e.width),
						height: String(e.height)
					})));
				}
			}
		});
	};
	var Selection = {
		setup: setup$2
	};

	var stateSelectorAdapter = function(editor, selector) {
		return function(buttonApi) {
			return editor.selection.selectorChangedWithUnbind(selector.join(','), buttonApi.setActive)
				.unbind;
		};
	};
	var register$1 = function(editor) {
		editor.ui.registry.addToggleButton('media', {
			tooltip: 'Insert/edit media',
			icon: 'embed',
			onAction: function() {
				editor.execCommand('mceMedia');
			},
			onSetup: stateSelectorAdapter(editor, [
				'img[data-mce-object]',
				'span[data-mce-object]',
				'div[data-ephox-embed-iri]'
			])
		});
		editor.ui.registry.addMenuItem('media', {
			icon: 'embed',
			text: 'Media...',
			onAction: function() {
				editor.execCommand('mceMedia');
			}
		});
	};
	var Buttons = {
		register: register$1
	};

	function Plugin() {
		global.add('media', function(editor) {
			Commands.register(editor);
			Buttons.register(editor);
			ResolveName.setup(editor);
			FilterContent.setup(editor);
			Selection.setup(editor);
			return Api.get(editor);
		});
	}

	Plugin();

}());